source('../settings/settings.R')
source('commonFunctions.R')
inputFileDrive1 <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=1, distPrev=DISTANCE_PREV, distNext=DISTANCE_NEXT))
inputFileDrive2 <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=2, distPrev=DISTANCE_PREV, distNext=DISTANCE_NEXT))
inputFileDrive3 <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=3, distPrev=DISTANCE_PREV, distNext=DISTANCE_NEXT))
inputFileDrive4 <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=4, distPrev=30, distNext=30))

drive1 <- read.csv(inputFileDrive1)
drive2 <- read.csv(inputFileDrive2)
drive3 <- read.csv(inputFileDrive3)

drive4 <- read.csv(inputFileDrive4, stringsAsFactors = T)
set.seed(43)
combinedDf <- cbind(drive4, 
                    drive1$MeanPP_Seg0, 
                    drive2$MeanPP, drive3$MeanPP,
                    drive2$StdPP, drive3$StdPP,
                    drive2$MeanPP_SegMax, drive3$MeanPP_SegMax, 
                    drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
                    drive2$StdPP_SegMax, drive3$StdPP_SegMax, 
                    drive2$StdPP_Seg0, drive3$StdPP_Seg0,
                    drive2$MeanPP_AccHigh, drive3$MeanPP_AccHigh,
                    drive2$X.MeanPP_AccLow, drive3$X.MeanPP_AccLow,
                    drive2$StdPP_AccHigh, drive3$StdPP_AccHigh,
                    drive2$StdPP_AccLow, drive3$StdPP_AccLow
                  )
names(combinedDf) <- c(names(drive4), 
                       "PP_Dev_1_Turning",
                       "PP_Dev_2", "PP_Dev_3", 
                       "Std_PP_2", "Std_PP_3",
                       "PP_Dev_2_Straight", "PP_Dev_3_Straight", 
                       "PP_Dev_2_Turning", "PP_Dev_3_Turning", 
                       "Std_PP_2_Straight", "Std_PP_3_Straight", 
                       "Std_PP_2_Turning", "Std_PP_3_Turning",
                       "Mean_PP_2_AccHigh", "Mean_PP_3_AccHigh",
                       "Mean_PP_2_AccLow", "Mean_PP_3_AccLow",
                       "Std_PP_2_AccHigh", "Std_PP_3_AccHigh",
                       "Std_PP_2_AccLow", "Std_PP_3_AccLow"
                       )

combinedDf$Subject <- paste0("#", str_pad(combinedDf$Subject, 2, pad="0"))
combinedDf$ActivityEncoded <- factor(ifelse(combinedDf$Activity == "NO", "1", ifelse(combinedDf$Activity == "C", "2", "3")))

# combinedDf$PP_Dev_2_Turning <- ifelse(combinedDf$PP_Dev_2_Turning > 0, combinedDf$PP_Dev_2_Turning, combinedDf$PP_Dev_2_Straight)
combinedDf_NoStressor <- combinedDf[combinedDf$Activity == "NO",]
combinedDf_Cognitive <- combinedDf[combinedDf$Activity == "C",]
combinedDf_Motoric <- combinedDf[combinedDf$Activity == "M",]

combinedDf_NoStressor$Subject <- as.factor(combinedDf_NoStressor$Subject)
combinedDf_Cognitive$Subject <- as.factor(combinedDf_Cognitive$Subject)
combinedDf_Motoric$Subject <- as.factor(combinedDf_Motoric$Subject)
COLOR_NORMAL <- list(color='rgb(120,120,120)')
COLOR_COGNITIVE <- list(color='rgb(158,202,225)')
COLOR_MOTORIC <- list(color='rgb(58,200,225)')
COLOR_FAILURE_PRIOR <- list(color='green')
COLOR_FAILURE <- list(color='red')
COLOR_COGNITIVE_ACC <- list(color='rgb(158,202,225)')
COLOR_MOTORIC_ACC <- list(color='rgb(58,200,225)')

bargap <- 6
yAxis <- list(
  title = "Arousal ΔPP [ln°C²]",
  range=c(-0.2, 0.6)
)

# Apply Otsu algorithm to select threshold
ppDev <- combinedDf$PP_After # PP_Dev
ppDevArray <- matrix(ppDev, nrow = 1,ncol = length(ppDev))
  
THRESHOLD_MILD = otsu(ppDevArray, range=c(min(ppDev), max(ppDev))) # Expected Threshold > 0.042
print(paste0('Threshold: ', THRESHOLD_MILD))
[1] "Threshold: 0.12638427734375"
MARKER_LINE_MILD = list(color="blue")
MARKER_LINE_EXTREME = list(color="red")
xAxis = list(
  title = "Subject",
  ticktext = combinedDf_NoStressor$Subject, 
  tickvals = seq(1, bargap * nrow(combinedDf_NoStressor), by=bargap),
  tickmode = "array"
)
combinedDf_NoStressor$SubjectLevel <- seq(1, bargap * nrow(combinedDf_NoStressor), by=bargap)
      
fig_NoStressor <- plot_ly(combinedDf_NoStressor, x = ~SubjectLevel, width=1000) %>%
  # add_trace(y = ~PP_Dev_2_Straight, name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
  # add_trace(y = ~PP_Dev_1_Turning, name = 'Normal - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  # add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  add_trace(type="bar", y = ~Mean_PP_2_AccHigh, width=1.58, name = 'ΔPP after HA in CD', marker=COLOR_COGNITIVE_ACC) %>% 
  # add_trace(y = ~Mean_PP_2_AccLow, name = 'Coginitive - Mean PP (Low Accel.)', marker=COLOR_ACC) %>% 
  
  # add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>% 
  # add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>% 
  add_trace(type="bar", y = ~Mean_PP_3_AccHigh, width=1.58, name = "ΔPP after HA in MD", marker=COLOR_MOTORIC_ACC) %>% 
  # add_trace(y = ~Mean_PP_3_AccLow, name = 'Motoric - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
  
  # add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>%
  add_trace(type="bar", y = ~PP_After, width=1.58, name = 'ΔPP after the catastrophic event', marker=COLOR_FAILURE) %>% 
  add_segments(x=-5, xend=bargap * nrow(combinedDf_NoStressor), y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Otsu Threshold",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', bargap=5, title=F) 

fig_NoStressor <- fig_NoStressor %>% config(mathjax = 'cdn')

htmltools::tagList(fig_NoStressor)
xAxis = list(
  title = "Subject",
  ticktext = combinedDf_Cognitive$Subject, 
  tickvals = seq(1, bargap * nrow(combinedDf_Cognitive), by=bargap),
  tickmode = "array"
)
combinedDf_Cognitive$SubjectLevel <- seq(1, bargap * nrow(combinedDf_Cognitive), by=bargap)

fig_Cognitive <- plot_ly(combinedDf_Cognitive, x = ~SubjectLevel, width=1000) %>%
  # add_trace(y = ~PP_Dev_2_Straight, name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
  # add_trace(y = ~PP_Dev_1_Turning, name = 'Normal - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  # add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  add_trace(type="bar", y = ~Mean_PP_2_AccHigh, width=1.58, name = 'ΔPP after HA in CD', marker=COLOR_COGNITIVE_ACC) %>% 
  # add_trace(y = ~Mean_PP_2_AccLow, name = 'Coginitive - Mean PP (Low Accel.)', marker=COLOR_ACC) %>% 
  
  # add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>% 
  # add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>% 
  add_trace(type="bar", y = ~Mean_PP_3_AccHigh, width=1.58, name = "ΔPP after HA in MD", marker=COLOR_MOTORIC_ACC) %>% 
  # add_trace(y = ~Mean_PP_3_AccLow, name = 'Motoric - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
  
  # add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>%
  add_trace(type="bar", y = ~PP_After, width=1.58, name = 'ΔPP after the catastrophic event', marker=COLOR_FAILURE) %>% 
  add_segments(x=-5, xend=bargap * nrow(combinedDf_NoStressor), y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Otsu Threshold",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', bargap=5, title=F)

htmltools::tagList(fig_Cognitive)
xAxis = list(
  title = "Subject",
  ticktext = combinedDf_Motoric$Subject, 
  tickvals = seq(1, bargap * nrow(combinedDf_Motoric), by=bargap),
  tickmode = "array"
)
combinedDf_Motoric$SubjectLevel <- seq(1, bargap * nrow(combinedDf_Motoric), by=bargap)

fig_Motoric <- plot_ly(combinedDf_Motoric, x = ~SubjectLevel, width=1000) %>%
  # add_trace(y = ~PP_Dev_2_Straight, name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
  # add_trace(y = ~PP_Dev_1_Turning, name = 'Normal - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  # add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>% 
  add_trace(type="bar", y = ~Mean_PP_2_AccHigh, width=1.58, name = 'ΔPP after HA in CD', marker=COLOR_COGNITIVE_ACC) %>% 
  # add_trace(y = ~Mean_PP_2_AccLow, name = 'Coginitive - Mean PP (Low Accel.)', marker=COLOR_ACC) %>% 
  
  # add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>% 
  # add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>% 
  add_trace(type="bar", y = ~Mean_PP_3_AccHigh, width=1.58, name = "ΔPP after HA in MD", marker=COLOR_MOTORIC_ACC) %>% 
  # add_trace(y = ~Mean_PP_3_AccLow, name = 'Motoric - Mean PP (Low Accel.)', marker=COLOR_ACC) %>%
  
  # add_trace(y = ~PP_Prior, name = 'Failure - Prior PP', marker=COLOR_FAILURE_PRIOR) %>%
  add_trace(type="bar", y = ~PP_After, width=1.58, name = 'ΔPP after the catastrophic event', marker=COLOR_FAILURE) %>% 
  add_segments(x=-5, xend=bargap * nrow(combinedDf_NoStressor), y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Otsu Threshold",
                           line=list(color="blue", dash = 'dot')) %>%
  # add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
  #                          line=list(color="darkred", dash = 'dot')) %>%
  layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', bargap=5, title=F)

htmltools::tagList(fig_Motoric)
library(nlme)
combinedDf$Subject = as.factor(combinedDf$Subject)
combinedDf$Activity = as.factor(combinedDf$Activity)
combinedDf$PP_Dev_Group = ifelse(combinedDf$PP_Dev > THRESHOLD_MILD, 1, 0)

Extract data for important features

importantFeaturesDf <- combinedDf %>% select(Subject, Std_PP_3, PP_Dev_2_Turning, Activity, PP_Dev, PP_Dev_Group)

Linear model with all variables

linearModel1 <- lm(PP_After ~ 
              + PP_Dev_2_Straight
              + PP_Dev_3_Straight
              + PP_Dev_2_Turning
              + PP_Dev_3_Turning
              + Std_PP_2_Straight
              + Std_PP_3_Straight
              + Std_PP_2_Turning
              + Std_PP_3_Turning
              + PP_Prior
              + factor(ActivityEncoded), 
            data=combinedDf)

# anova(model)
summary(linearModel1)

Call:
lm(formula = PP_After ~ +PP_Dev_2_Straight + PP_Dev_3_Straight + 
    PP_Dev_2_Turning + PP_Dev_3_Turning + Std_PP_2_Straight + 
    Std_PP_3_Straight + Std_PP_2_Turning + Std_PP_3_Turning + 
    PP_Prior + factor(ActivityEncoded), data = combinedDf)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.066469 -0.030574 -0.004234  0.016063  0.091691 

Coefficients:
                         Estimate Std. Error t value Pr(>|t|)   
(Intercept)              -0.07677    0.08187  -0.938  0.37286   
PP_Dev_2_Straight         0.55986    0.32689   1.713  0.12093   
PP_Dev_3_Straight        -0.88019    0.41257  -2.133  0.06168 . 
PP_Dev_2_Turning         -0.27590    0.42870  -0.644  0.53590   
PP_Dev_3_Turning          0.68958    0.44285   1.557  0.15386   
Std_PP_2_Straight         0.51998    1.23819   0.420  0.68437   
Std_PP_3_Straight         1.17270    0.65813   1.782  0.10846   
Std_PP_2_Turning         -0.39849    1.57661  -0.253  0.80614   
Std_PP_3_Turning         -0.41772    1.11291  -0.375  0.71610   
PP_Prior                  0.77406    0.20609   3.756  0.00451 **
factor(ActivityEncoded)2  0.09572    0.06604   1.449  0.18119   
factor(ActivityEncoded)3  0.14416    0.05163   2.792  0.02098 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.06346 on 9 degrees of freedom
Multiple R-squared:  0.9231,    Adjusted R-squared:  0.8292 
F-statistic: 9.824 on 11 and 9 DF,  p-value: 0.0009588
plot(linearModel1)

linearModel1 <- lm(PP_After ~ 
                Mean_PP_2_AccHigh
              + Mean_PP_2_AccLow
              + Mean_PP_3_AccHigh
              + Mean_PP_3_AccLow
              + Std_PP_2_AccHigh
              + Std_PP_2_AccLow
              + Std_PP_3_AccHigh
              + Std_PP_3_AccLow
              # + PP_Prior
              + factor(ActivityEncoded), 
            data=combinedDf)

# anova(model)
summary(linearModel1)

Call:
lm(formula = PP_After ~ Mean_PP_2_AccHigh + Mean_PP_2_AccLow + 
    Mean_PP_3_AccHigh + Mean_PP_3_AccLow + Std_PP_2_AccHigh + 
    Std_PP_2_AccLow + Std_PP_3_AccHigh + Std_PP_3_AccLow + factor(ActivityEncoded), 
    data = combinedDf)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.103753 -0.053453  0.008069  0.042675  0.072533 

Coefficients:
                         Estimate Std. Error t value Pr(>|t|)   
(Intercept)              -0.38487    0.10071  -3.821  0.00337 **
Mean_PP_2_AccHigh         1.92518    0.64384   2.990  0.01357 * 
Mean_PP_2_AccLow         -1.57985    0.64227  -2.460  0.03369 * 
Mean_PP_3_AccHigh         3.09455    0.79809   3.877  0.00307 **
Mean_PP_3_AccLow         -2.36870    0.76639  -3.091  0.01143 * 
Std_PP_2_AccHigh          4.76271    4.11946   1.156  0.27449   
Std_PP_2_AccLow          -4.20550    2.84707  -1.477  0.17043   
Std_PP_3_AccHigh          1.29380    1.87829   0.689  0.50660   
Std_PP_3_AccLow           2.99288    2.18566   1.369  0.20086   
factor(ActivityEncoded)2  0.20599    0.05116   4.026  0.00241 **
factor(ActivityEncoded)3  0.15111    0.05411   2.793  0.01903 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.07786 on 10 degrees of freedom
Multiple R-squared:  0.8714,    Adjusted R-squared:  0.7428 
F-statistic: 6.777 on 10 and 10 DF,  p-value: 0.002822
plot(linearModel1)

With Prior

linearModelWPrior <- lm(PP_After ~ 
                Mean_PP_2_AccHigh
              + Mean_PP_2_AccLow
              + Mean_PP_3_AccHigh
              + Mean_PP_3_AccLow
              + Std_PP_2_AccHigh
              + Std_PP_2_AccLow
              + Std_PP_3_AccHigh
              + Std_PP_3_AccLow
              + PP_Prior
              + factor(ActivityEncoded), 
            data=combinedDf)

# anova(model)
summary(linearModelWPrior)

Call:
lm(formula = PP_After ~ Mean_PP_2_AccHigh + Mean_PP_2_AccLow + 
    Mean_PP_3_AccHigh + Mean_PP_3_AccLow + Std_PP_2_AccHigh + 
    Std_PP_2_AccLow + Std_PP_3_AccHigh + Std_PP_3_AccLow + PP_Prior + 
    factor(ActivityEncoded), data = combinedDf)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.052370 -0.020532  0.000148  0.024951  0.048104 

Coefficients:
                         Estimate Std. Error t value Pr(>|t|)   
(Intercept)              -0.23196    0.07296  -3.179  0.01120 * 
Mean_PP_2_AccHigh         1.42749    0.41884   3.408  0.00777 **
Mean_PP_2_AccLow         -1.19436    0.41079  -2.907  0.01738 * 
Mean_PP_3_AccHigh         1.51586    0.62870   2.411  0.03918 * 
Mean_PP_3_AccLow         -1.29049    0.54487  -2.368  0.04202 * 
Std_PP_2_AccHigh          6.67707    2.60696   2.561  0.03062 * 
Std_PP_2_AccLow          -4.23334    1.77260  -2.388  0.04068 * 
Std_PP_3_AccHigh         -0.84881    1.28095  -0.663  0.52417   
Std_PP_3_AccLow           3.09137    1.36101   2.271  0.04925 * 
PP_Prior                  0.70129    0.17111   4.099  0.00268 **
factor(ActivityEncoded)2  0.12193    0.03789   3.218  0.01052 * 
factor(ActivityEncoded)3  0.16048    0.03376   4.753  0.00104 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.04847 on 9 degrees of freedom
Multiple R-squared:  0.9551,    Adjusted R-squared:  0.9003 
F-statistic: 17.42 on 11 and 9 DF,  p-value: 9.605e-05
plot(linearModelWPrior)

linearModel3 <- lm(PP_After ~ 
                Mean_PP_2_AccHigh
              + Mean_PP_2_AccLow
              + Mean_PP_3_AccHigh
              + Mean_PP_3_AccLow
              # + PP_Prior
              + factor(ActivityEncoded), 
            data=combinedDf)

# anova(model)
summary(linearModel3)

Call:
lm(formula = PP_After ~ Mean_PP_2_AccHigh + Mean_PP_2_AccLow + 
    Mean_PP_3_AccHigh + Mean_PP_3_AccLow + factor(ActivityEncoded), 
    data = combinedDf)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.106576 -0.057424  0.004053  0.045385  0.144030 

Coefficients:
                         Estimate Std. Error t value Pr(>|t|)   
(Intercept)              -0.22818    0.06871  -3.321  0.00505 **
Mean_PP_2_AccHigh         1.94837    0.68471   2.846  0.01296 * 
Mean_PP_2_AccLow         -1.44379    0.68502  -2.108  0.05357 . 
Mean_PP_3_AccHigh         3.05982    0.76503   4.000  0.00132 **
Mean_PP_3_AccLow         -2.51493    0.72785  -3.455  0.00386 **
factor(ActivityEncoded)2  0.18649    0.05498   3.392  0.00438 **
factor(ActivityEncoded)3  0.19053    0.04764   3.999  0.00132 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.08544 on 14 degrees of freedom
Multiple R-squared:  0.7832,    Adjusted R-squared:  0.6903 
F-statistic:  8.43 on 6 and 14 DF,  p-value: 0.0005323
plot(linearModel3)

# Export the anova table
library(xtable)
lmCoeffs <- summary(linearModel3)$coefficients
lmAnova <- anova(linearModel3)

print(xtable(lmCoeffs, digits=c(0,5,5,5,5)))
% latex table generated in R 3.6.1 by xtable 1.8-4 package
% Wed Jul 15 01:02:05 2020
\begin{table}[ht]
\centering
\begin{tabular}{rrrrr}
  \hline
 & Estimate & Std. Error & t value & Pr($>$$|$t$|$) \\ 
  \hline
(Intercept) & -0.22818 & 0.06871 & -3.32083 & 0.00505 \\ 
  Mean\_PP\_2\_AccHigh & 1.94837 & 0.68471 & 2.84555 & 0.01296 \\ 
  Mean\_PP\_2\_AccLow & -1.44379 & 0.68502 & -2.10767 & 0.05357 \\ 
  Mean\_PP\_3\_AccHigh & 3.05982 & 0.76503 & 3.99960 & 0.00132 \\ 
  Mean\_PP\_3\_AccLow & -2.51493 & 0.72785 & -3.45527 & 0.00386 \\ 
  factor(ActivityEncoded)2 & 0.18649 & 0.05498 & 3.39189 & 0.00438 \\ 
  factor(ActivityEncoded)3 & 0.19053 & 0.04764 & 3.99910 & 0.00132 \\ 
   \hline
\end{tabular}
\end{table}
print(xtable(lmAnova), digits=c(0,5,5,5,5))
% latex table generated in R 3.6.1 by xtable 1.8-4 package
% Wed Jul 15 01:02:05 2020
\begin{table}[ht]
\centering
\begin{tabular}{lrrrrr}
  \hline
 & Df & Sum Sq & Mean Sq & F value & Pr($>$F) \\ 
  \hline
Mean\_PP\_2\_AccHigh & 1 & 0.15 & 0.15 & 20.66 & 0.0005 \\ 
  Mean\_PP\_2\_AccLow & 1 & 0.00 & 0.00 & 0.05 & 0.8310 \\ 
  Mean\_PP\_3\_AccHigh & 1 & 0.01 & 0.01 & 1.42 & 0.2535 \\ 
  Mean\_PP\_3\_AccLow & 1 & 0.06 & 0.06 & 8.61 & 0.0109 \\ 
  factor(ActivityEncoded) & 2 & 0.14 & 0.07 & 9.92 & 0.0021 \\ 
  Residuals & 14 & 0.10 & 0.01 &  &  \\ 
   \hline
\end{tabular}
\end{table}
ppAfter <- combinedDf$PP_After
ppAfterArray <- matrix(ppAfter, nrow = 1,ncol = length(ppAfter))
  
thresholdPPAfter <- otsu(ppAfterArray, range=c(min(ppAfter), max(ppAfter))) # Expected Threshold > 0.042
print(paste0('Threshold: ', thresholdPPAfter))
[1] "Threshold: 0.12638427734375"
selectedDf <- combinedDf %>% select(
                  "Subject", "Activity", "PP_After", # "PP_Prior",
                  "Mean_PP_2_AccHigh", "Mean_PP_3_AccHigh",
                  "Mean_PP_2_AccLow", "Mean_PP_3_AccLow",
                  # "Std_PP_2_AccHigh", "Std_PP_3_AccHigh",
                  # "Std_PP_2_AccLow", "Std_PP_3_AccLow"
                  )

selectedDf$Subject <- NULL
selectedDf$Activity_NO <- ifelse(selectedDf$Activity == "NO", 1, 0)
selectedDf$Activity_C <- ifelse(selectedDf$Activity == "C", 1, 0)
selectedDf$Activity_M <- ifelse(selectedDf$Activity == "M", 1, 0)
selectedDf$Activity <- NULL

# selectedDf$PP_Dev_1_Turning <- NULL
# selectedDf$Std_PP_2_Straight <- NULL
# selectedDf$Std_PP_2_Turning <- NULL
# selectedDf$Std_PP_3_Straight <- NULL
# selectedDf$Std_PP_3_Turning <- NULL
# 
# # According to Linear model
# selectedDf$PP_Dev_2_Straight <- abs(selectedDf$PP_Dev_2_Straight)
# selectedDf$PP_Dev_3_Straight <- abs(selectedDf$PP_Dev_3_Straight)
# selectedDf$PP_Dev_2_Turning <- abs(selectedDf$PP_Dev_2_Turning)
# selectedDf$PP_Dev_3_Turning <- abs(selectedDf$PP_Dev_3_Turning)
# selectedDf$PP_Prior <- abs(selectedDf$PP_Prior) # NULL

selectedDf$Class <- ifelse(selectedDf$PP_After >= thresholdPPAfter, T, F)
selectedDf$PP_After <- NULL

print(names(selectedDf))
[1] "Mean_PP_2_AccHigh" "Mean_PP_3_AccHigh" "Mean_PP_2_AccLow"  "Mean_PP_3_AccLow"  "Activity_NO"       "Activity_C"       
[7] "Activity_M"        "Class"            
# library(mefa)
# combinedDf <- rep(combinedDf, 10) 
set.seed(39)
n_folds <- 3
params <- param <- list(objective       = "binary:logistic", 
               booster          = "gbtree",
               eval_metric      = "auc",
               eta              = 0.1,
               max_depth        = 10,
               alpha            = 1,
               lambda           = 0,
               gamma            = 0.45,
               min_child_weight = 0.3,
               subsample        = 0.5,
               colsample_bytree = 1)
           
# XGBoost Model         
xgb_m <- xgb.cv(   params               = param,
                  data = as.matrix(selectedDf %>% select(-Class)) ,
                  label =  selectedDf$Class,
                  nrounds             = 100,
                  verbose             = F,
                  prediction          = T,
                  maximize            = F, # Change this value to F will help to run with more itineration
                  nfold               = n_folds,
                  metrics             = c("auc", "error"),
                  early_stopping_rounds = 50,
                  stratified            = T,
                  scale_pos_weight      = 1)

# xgb_m$evaluation_log[xgb_m$best_iteration,"test_auc_mean"]
xgb_m$evaluation_log[xgb_m$best_iteration,]
NA

Performance Metrics

# Prediction
selectedDf$clsPred <- round(xgb_m$pred)

computePerformanceResults <- function(sdat){
  sdat = sdat[complete.cases(sdat),]
  acc = sum(sdat[,1] == sdat[,2])/nrow(sdat)
  conf_mat = table(sdat)
  specif = conf_mat[1,1]/sum(conf_mat[,1])
  sensiv = conf_mat[2,2]/sum(conf_mat[,2])
  preci =  conf_mat[2,2]/sum(conf_mat[2,])
  npv =    conf_mat[1,1]/sum(conf_mat[1,])
  return(c(acc,specif,sensiv,preci,npv))
}

# Get average performance
performance <- computePerformanceResults(selectedDf %>% select(Class, clsPred))
acc <- performance[1]
prec <- performance[4]
recall <- performance[3]
spec <- performance[2]
npv <- performance[5]
f1 <- (2 * recall * prec) / (recall + prec)
auc <- as.numeric(xgb_m$evaluation_log[xgb_m$best_iteration, "test_auc_mean"])

print(paste("Accuracy=", round(acc, 2)))
[1] "Accuracy= 0.71"
print(paste("Precision=", round(prec, 2)))
[1] "Precision= 0.44"
print(paste("Recall=", round(recall, 2)))
[1] "Recall= 0.8"
print(paste("Specificity=", round(spec, 2)))
[1] "Specificity= 0.69"
print(paste("NPV=", round(npv, 2)))
[1] "NPV= 0.92"
print(paste("F1=", round(f1, 2)))
[1] "F1= 0.57"
print(paste("AUC=", round(auc, 2)))
[1] "AUC= 0.84"
# Importance
bst <- xgboost(   params               = param,
                  data = as.matrix(selectedDf %>% select(-c(Class, clsPred))) ,
                  label =  selectedDf$Class,
                  nrounds             = 100,
                  verbose             = F,
                  prediction          = T,
                  maximize            = F, # Change this value to F will help to run with more itineration
                  nfold               = n_folds,
                  metrics             = c("auc", "error"),
                  early_stopping_rounds = 50,
                  stratified            = T,
                  scale_pos_weight      = 1)
importanceDf <- xgb.importance(colnames(selectedDf %>% select(-c(Class, clsPred))), model = bst)
print(importanceDf)
library(pROC)

dfROC <- pROC::roc(response = ifelse(selectedDf$Class==T, 1, 0),
               predictor = round(xgb_m$pred),
               levels=c(0, 1), direction = "<")

# it = which.max(xgb_m$evaluation_log$test_auc_mean)
# best.iter = xgb_m$evaluation_log$iter[it]
# best.iter 

plot(pROC::roc(response = ifelse(selectedDf$Class==T, 1, 0),
               predictor = round(xgb_m$pred),
               levels=c(0, 1), direction = "<"), 
     legacy.axes = TRUE,
     main="ROC Curve", 
     lwd=1.5) 

Plot feature importance

yAxis <- list(
  title = 'Importance',
  range=c(0.0, 1.0)
)
xAxis <- list(
  title = ''
)

importanceDf$Feature <- factor(importanceDf$Feature, levels = importanceDf[order(-Gain),]$Feature)
fig_Importance <- plot_ly(importanceDf, x = ~Feature, y = ~Gain, type = 'bar', name = 'Gain', width=600) %>%
  add_trace(y = ~Cover, name = 'Cover') %>% 
  add_trace(y = ~Frequency, name = 'Frequency') %>% 
  layout(yaxis = yAxis, xaxis=xAxis, barmode = 'group', title="Feature Importance") %>% 
  config(.Last.value, mathjax = 'cdn')

htmltools::tagList(fig_Importance)
actualCluster <- data.frame(cbind(as.character(combinedDf$Subject), selectedDf$Class))
names(actualCluster) <- c("Subject", "Class")
actualCluster
# actualCluster[order(Class),]
library(factoextra)
library(cluster)
clusteringDf <- combinedDf %>% select("Mean_PP_2_AccHigh", "Mean_PP_3_AccHigh") #(importanceDf$Feature[1:3])
rownames(selectedDf) <- paste0(combinedDf$Subject)
rownames(clusteringDf) <- paste0(combinedDf$Subject)
fit <- kmeans(clusteringDf, 3)
# clusplot(clusteringDf, fit$cluster, color=TRUE, shade=TRUE, labels=2, lines=0)
fviz_cluster(fit, data=selectedDf)

library(dendextend)

NUMBER_OF_CLUSTERS = 4
CLUSTER_COLORS <- c("red", "blue", color_darkpink, color_darkpink)

color_darkpink = "#e75480"
CLUSTER_BRANCH_COLORS <- CLUSTER_COLORS[1:NUMBER_OF_CLUSTERS]
CLUSTER_LABEL_COLORS <- CLUSTER_COLORS[1:NUMBER_OF_CLUSTERS]

behavioralMatrixClustering <- as.matrix(clusteringDf)
rownames(behavioralMatrixClustering) <- paste0(combinedDf$Subject)
distMatrix <- dist(behavioralMatrixClustering, method="manhattan")
hresults <- distMatrix %>% hclust(method="complete")

hc <- hresults %>% 
      as.dendrogram %>%
      set("nodes_cex", NUMBER_OF_CLUSTERS) %>%
      set("labels_col", value = CLUSTER_LABEL_COLORS, k=NUMBER_OF_CLUSTERS) %>%
      # set("leaves_pch", 19) %>%
      # set("leaves_col", value = c("gray"), k=NUMBER_OF_CLUSTERS) %>%    
      set("branches_k_color", value=CLUSTER_BRANCH_COLORS, k=NUMBER_OF_CLUSTERS)

plot(hc)
legend("topright", 
     title="Drive=Failure \nChange of Arousal",
     legend = c("Exceptional Increase" , "Noticable Increase" , "No-change or Decrease"), 
     col = c("red", "pink" , "blue"),
     pch = c(20,20,20), bty = "n",  pt.cex = 1.5, cex = 0.8 , 
     text.col = "black", horiz = FALSE, inset = c(0.0, 0.1))

NUMBER_OF_CLUSTERS <- 2
CLUSTER_COLORS <- c("red", "blue", color_darkpink, color_darkpink)

color_darkpink = "#e75480"
CLUSTER_BRANCH_COLORS <- CLUSTER_COLORS[1:NUMBER_OF_CLUSTERS]
CLUSTER_LABEL_COLORS <- CLUSTER_COLORS[1:NUMBER_OF_CLUSTERS]

combinedDf$isM <- ifelse(combinedDf$Activity == "M", 0.1, 0)
combinedDf$isC <- ifelse(combinedDf$Activity == "C", 0.1, 0)
combinedDf$isN <- ifelse(combinedDf$Activity == "NO", 0.1, 0)

behavioralMatrixClustering <- as.matrix(combinedDf %>% select("PP_After", "isM", "isC", "isN"))
rownames(behavioralMatrixClustering) <- paste0(combinedDf$Subject)
distMatrix <- dist(behavioralMatrixClustering, method="manhattan")
hresults <- distMatrix %>% hclust(method="complete")

hc <- hresults %>% 
      as.dendrogram %>%
      set("nodes_cex", NUMBER_OF_CLUSTERS) %>%
      set("labels_col", value = CLUSTER_LABEL_COLORS, k=NUMBER_OF_CLUSTERS) %>%
      # set("leaves_pch", 19) %>%
      # set("leaves_col", value = c("gray"), k=NUMBER_OF_CLUSTERS) %>%    
      set("branches_k_color", value=CLUSTER_BRANCH_COLORS, k=NUMBER_OF_CLUSTERS)

plot(hc)
legend("topright", 
     title="Drive=Failure \nChange of Arousal",
     legend = c("Exceptional Increase" , "Noticable Increase" , "No-change or Decrease"), 
     col = c("red", "pink" , "blue"),
     pch = c(20,20,20), bty = "n",  pt.cex = 1.5, cex = 0.8 , 
     text.col = "black", horiz = FALSE, inset = c(0.0, 0.1))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnNvdXJjZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MuUicpCnNvdXJjZSgnY29tbW9uRnVuY3Rpb25zLlInKQpgYGAKCmBgYHtyfQppbnB1dEZpbGVEcml2ZTEgPC0gc3RyX2ludGVycCgiLi4vZGF0YS9wcm9jZXNzZWQvYW5hbHlzaXMvVFQxX0RyaXZlXyR7ZHJpdmV9X1BQXyR7ZGlzdFByZXZ9bV8ke2Rpc3ROZXh0fW0uY3N2IiwgbGlzdChkcml2ZT0xLCBkaXN0UHJldj1ESVNUQU5DRV9QUkVWLCBkaXN0TmV4dD1ESVNUQU5DRV9ORVhUKSkKaW5wdXRGaWxlRHJpdmUyIDwtIHN0cl9pbnRlcnAoIi4uL2RhdGEvcHJvY2Vzc2VkL2FuYWx5c2lzL1RUMV9Ecml2ZV8ke2RyaXZlfV9QUF8ke2Rpc3RQcmV2fW1fJHtkaXN0TmV4dH1tLmNzdiIsIGxpc3QoZHJpdmU9MiwgZGlzdFByZXY9RElTVEFOQ0VfUFJFViwgZGlzdE5leHQ9RElTVEFOQ0VfTkVYVCkpCmlucHV0RmlsZURyaXZlMyA8LSBzdHJfaW50ZXJwKCIuLi9kYXRhL3Byb2Nlc3NlZC9hbmFseXNpcy9UVDFfRHJpdmVfJHtkcml2ZX1fUFBfJHtkaXN0UHJldn1tXyR7ZGlzdE5leHR9bS5jc3YiLCBsaXN0KGRyaXZlPTMsIGRpc3RQcmV2PURJU1RBTkNFX1BSRVYsIGRpc3ROZXh0PURJU1RBTkNFX05FWFQpKQppbnB1dEZpbGVEcml2ZTQgPC0gc3RyX2ludGVycCgiLi4vZGF0YS9wcm9jZXNzZWQvYW5hbHlzaXMvVFQxX0RyaXZlXyR7ZHJpdmV9X1BQXyR7ZGlzdFByZXZ9bV8ke2Rpc3ROZXh0fW0uY3N2IiwgbGlzdChkcml2ZT00LCBkaXN0UHJldj0zMCwgZGlzdE5leHQ9MzApKQoKZHJpdmUxIDwtIHJlYWQuY3N2KGlucHV0RmlsZURyaXZlMSkKZHJpdmUyIDwtIHJlYWQuY3N2KGlucHV0RmlsZURyaXZlMikKZHJpdmUzIDwtIHJlYWQuY3N2KGlucHV0RmlsZURyaXZlMykKCmRyaXZlNCA8LSByZWFkLmNzdihpbnB1dEZpbGVEcml2ZTQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUKQpgYGAKCmBgYHtyfQpzZXQuc2VlZCg0MykKY29tYmluZWREZiA8LSBjYmluZChkcml2ZTQsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMSRNZWFuUFBfU2VnMCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUCwgZHJpdmUzJE1lYW5QUCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFAsIGRyaXZlMyRTdGRQUCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZ01heCwgZHJpdmUzJE1lYW5QUF9TZWdNYXgsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnMCwgZHJpdmUzJE1lYW5QUF9TZWcwLAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9TZWdNYXgsIGRyaXZlMyRTdGRQUF9TZWdNYXgsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9TZWcwLCBkcml2ZTMkU3RkUFBfU2VnMCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX0FjY0hpZ2gsIGRyaXZlMyRNZWFuUFBfQWNjSGlnaCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkWC5NZWFuUFBfQWNjTG93LCBkcml2ZTMkWC5NZWFuUFBfQWNjTG93LAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUF9BY2NIaWdoLCBkcml2ZTMkU3RkUFBfQWNjSGlnaCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFBfQWNjTG93LCBkcml2ZTMkU3RkUFBfQWNjTG93CiAgICAgICAgICAgICAgICAgICkKbmFtZXMoY29tYmluZWREZikgPC0gYyhuYW1lcyhkcml2ZTQpLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzFfVHVybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yIiwgIlBQX0Rldl8zIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yIiwgIlN0ZF9QUF8zIiwKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzJfU3RyYWlnaHQiLCAiUFBfRGV2XzNfU3RyYWlnaHQiLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzJfVHVybmluZyIsICJQUF9EZXZfM19UdXJuaW5nIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yX1N0cmFpZ2h0IiwgIlN0ZF9QUF8zX1N0cmFpZ2h0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yX1R1cm5pbmciLCAiU3RkX1BQXzNfVHVybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgIk1lYW5fUFBfMl9BY2NIaWdoIiwgIk1lYW5fUFBfM19BY2NIaWdoIiwKICAgICAgICAgICAgICAgICAgICAgICAiTWVhbl9QUF8yX0FjY0xvdyIsICJNZWFuX1BQXzNfQWNjTG93IiwKICAgICAgICAgICAgICAgICAgICAgICAiU3RkX1BQXzJfQWNjSGlnaCIsICJTdGRfUFBfM19BY2NIaWdoIiwKICAgICAgICAgICAgICAgICAgICAgICAiU3RkX1BQXzJfQWNjTG93IiwgIlN0ZF9QUF8zX0FjY0xvdyIKICAgICAgICAgICAgICAgICAgICAgICApCgpjb21iaW5lZERmJFN1YmplY3QgPC0gcGFzdGUwKCIjIiwgc3RyX3BhZChjb21iaW5lZERmJFN1YmplY3QsIDIsIHBhZD0iMCIpKQpjb21iaW5lZERmJEFjdGl2aXR5RW5jb2RlZCA8LSBmYWN0b3IoaWZlbHNlKGNvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIk5PIiwgIjEiLCBpZmVsc2UoY29tYmluZWREZiRBY3Rpdml0eSA9PSAiQyIsICIyIiwgIjMiKSkpCgojIGNvbWJpbmVkRGYkUFBfRGV2XzJfVHVybmluZyA8LSBpZmVsc2UoY29tYmluZWREZiRQUF9EZXZfMl9UdXJuaW5nID4gMCwgY29tYmluZWREZiRQUF9EZXZfMl9UdXJuaW5nLCBjb21iaW5lZERmJFBQX0Rldl8yX1N0cmFpZ2h0KQpgYGAKCmBgYHtyfQpjb21iaW5lZERmX05vU3RyZXNzb3IgPC0gY29tYmluZWREZltjb21iaW5lZERmJEFjdGl2aXR5ID09ICJOTyIsXQpjb21iaW5lZERmX0NvZ25pdGl2ZSA8LSBjb21iaW5lZERmW2NvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIkMiLF0KY29tYmluZWREZl9Nb3RvcmljIDwtIGNvbWJpbmVkRGZbY29tYmluZWREZiRBY3Rpdml0eSA9PSAiTSIsXQoKY29tYmluZWREZl9Ob1N0cmVzc29yJFN1YmplY3QgPC0gYXMuZmFjdG9yKGNvbWJpbmVkRGZfTm9TdHJlc3NvciRTdWJqZWN0KQpjb21iaW5lZERmX0NvZ25pdGl2ZSRTdWJqZWN0IDwtIGFzLmZhY3Rvcihjb21iaW5lZERmX0NvZ25pdGl2ZSRTdWJqZWN0KQpjb21iaW5lZERmX01vdG9yaWMkU3ViamVjdCA8LSBhcy5mYWN0b3IoY29tYmluZWREZl9Nb3RvcmljJFN1YmplY3QpCmBgYAoKYGBge3J9CkNPTE9SX05PUk1BTCA8LSBsaXN0KGNvbG9yPSdyZ2IoMTIwLDEyMCwxMjApJykKQ09MT1JfQ09HTklUSVZFIDwtIGxpc3QoY29sb3I9J3JnYigxNTgsMjAyLDIyNSknKQpDT0xPUl9NT1RPUklDIDwtIGxpc3QoY29sb3I9J3JnYig1OCwyMDAsMjI1KScpCkNPTE9SX0ZBSUxVUkVfUFJJT1IgPC0gbGlzdChjb2xvcj0nZ3JlZW4nKQpDT0xPUl9GQUlMVVJFIDwtIGxpc3QoY29sb3I9J3JlZCcpCkNPTE9SX0NPR05JVElWRV9BQ0MgPC0gbGlzdChjb2xvcj0ncmdiKDE1OCwyMDIsMjI1KScpCkNPTE9SX01PVE9SSUNfQUNDIDwtIGxpc3QoY29sb3I9J3JnYig1OCwyMDAsMjI1KScpCgpiYXJnYXAgPC0gNgp5QXhpcyA8LSBsaXN0KAogIHRpdGxlID0gIkFyb3VzYWwgzpRQUCBbbG7CsEPCsl0iLAogIHJhbmdlPWMoLTAuMiwgMC42KQopCgojIEFwcGx5IE90c3UgYWxnb3JpdGhtIHRvIHNlbGVjdCB0aHJlc2hvbGQKcHBEZXYgPC0gY29tYmluZWREZiRQUF9BZnRlciAjIFBQX0RldgpwcERldkFycmF5IDwtIG1hdHJpeChwcERldiwgbnJvdyA9IDEsbmNvbCA9IGxlbmd0aChwcERldikpCiAgClRIUkVTSE9MRF9NSUxEID0gb3RzdShwcERldkFycmF5LCByYW5nZT1jKG1pbihwcERldiksIG1heChwcERldikpKSAjIEV4cGVjdGVkIFRocmVzaG9sZCA+IDAuMDQyCnByaW50KHBhc3RlMCgnVGhyZXNob2xkOiAnLCBUSFJFU0hPTERfTUlMRCkpCgpNQVJLRVJfTElORV9NSUxEID0gbGlzdChjb2xvcj0iYmx1ZSIpCk1BUktFUl9MSU5FX0VYVFJFTUUgPSBsaXN0KGNvbG9yPSJyZWQiKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZ9CnhBeGlzID0gbGlzdCgKICB0aXRsZSA9ICJTdWJqZWN0IiwKICB0aWNrdGV4dCA9IGNvbWJpbmVkRGZfTm9TdHJlc3NvciRTdWJqZWN0LCAKICB0aWNrdmFscyA9IHNlcSgxLCBiYXJnYXAgKiBucm93KGNvbWJpbmVkRGZfTm9TdHJlc3NvciksIGJ5PWJhcmdhcCksCiAgdGlja21vZGUgPSAiYXJyYXkiCikKY29tYmluZWREZl9Ob1N0cmVzc29yJFN1YmplY3RMZXZlbCA8LSBzZXEoMSwgYmFyZ2FwICogbnJvdyhjb21iaW5lZERmX05vU3RyZXNzb3IpLCBieT1iYXJnYXApCiAgICAgIApmaWdfTm9TdHJlc3NvciA8LSBwbG90X2x5KGNvbWJpbmVkRGZfTm9TdHJlc3NvciwgeCA9IH5TdWJqZWN0TGV2ZWwsIHdpZHRoPTEwMDApICU+JQogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfU3RyYWlnaHQsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfMV9UdXJuaW5nLCBuYW1lID0gJ05vcm1hbCAtIE1lYW4gUFAgKFR1cm5pbmcpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UodHlwZT0iYmFyIiwgeSA9IH5NZWFuX1BQXzJfQWNjSGlnaCwgd2lkdGg9MS41OCwgbmFtZSA9ICfOlFBQIGFmdGVyIEhBIGluIENEJywgbWFya2VyPUNPTE9SX0NPR05JVElWRV9BQ0MpICU+JSAKICAjIGFkZF90cmFjZSh5ID0gfk1lYW5fUFBfMl9BY2NMb3csIG5hbWUgPSAnQ29naW5pdGl2ZSAtIE1lYW4gUFAgKExvdyBBY2NlbC4pJywgbWFya2VyPUNPTE9SX0FDQykgJT4lIAogIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHR5cGU9ImJhciIsIHkgPSB+TWVhbl9QUF8zX0FjY0hpZ2gsIHdpZHRoPTEuNTgsIG5hbWUgPSAizpRQUCBhZnRlciBIQSBpbiBNRCIsIG1hcmtlcj1DT0xPUl9NT1RPUklDX0FDQykgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+TWVhbl9QUF8zX0FjY0xvdywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoTG93IEFjY2VsLiknLCBtYXJrZXI9Q09MT1JfQUNDKSAlPiUKICAKICAjIGFkZF90cmFjZSh5ID0gflBQX1ByaW9yLCBuYW1lID0gJ0ZhaWx1cmUgLSBQcmlvciBQUCcsIG1hcmtlcj1DT0xPUl9GQUlMVVJFX1BSSU9SKSAlPiUKICBhZGRfdHJhY2UodHlwZT0iYmFyIiwgeSA9IH5QUF9BZnRlciwgd2lkdGg9MS41OCwgbmFtZSA9ICfOlFBQIGFmdGVyIHRoZSBjYXRhc3Ryb3BoaWMgZXZlbnQnLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PS01LCB4ZW5kPWJhcmdhcCAqIG5yb3coY29tYmluZWREZl9Ob1N0cmVzc29yKSwgeSA9IFRIUkVTSE9MRF9NSUxELCB5ZW5kID0gVEhSRVNIT0xEX01JTEQsIG5hbWU9Ik90c3UgVGhyZXNob2xkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgIyBhZGRfc2VnbWVudHMoeD0iIzAxIiwgeGVuZD0iIzQxIiwgeSA9IFRIUkVTSE9MRF9FWFRSRU1FLCB5ZW5kID0gVEhSRVNIT0xEX0VYVFJFTUUsIG5hbWU9IlRocmVzaG9sZDogRXh0cmVtZSBDaGFuZ2Ugb2YgUFAiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iZGFya3JlZCIsIGRhc2ggPSAnZG90JykpICU+JQogIGxheW91dCh5YXhpcyA9IHlBeGlzLCB4YXhpcz14QXhpcywgYmFybW9kZSA9ICdncm91cCcsIGJhcmdhcD01LCB0aXRsZT1GKSAKCmZpZ19Ob1N0cmVzc29yIDwtIGZpZ19Ob1N0cmVzc29yICU+JSBjb25maWcobWF0aGpheCA9ICdjZG4nKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Ob1N0cmVzc29yKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZ9CnhBeGlzID0gbGlzdCgKICB0aXRsZSA9ICJTdWJqZWN0IiwKICB0aWNrdGV4dCA9IGNvbWJpbmVkRGZfQ29nbml0aXZlJFN1YmplY3QsIAogIHRpY2t2YWxzID0gc2VxKDEsIGJhcmdhcCAqIG5yb3coY29tYmluZWREZl9Db2duaXRpdmUpLCBieT1iYXJnYXApLAogIHRpY2ttb2RlID0gImFycmF5IgopCmNvbWJpbmVkRGZfQ29nbml0aXZlJFN1YmplY3RMZXZlbCA8LSBzZXEoMSwgYmFyZ2FwICogbnJvdyhjb21iaW5lZERmX0NvZ25pdGl2ZSksIGJ5PWJhcmdhcCkKCmZpZ19Db2duaXRpdmUgPC0gcGxvdF9seShjb21iaW5lZERmX0NvZ25pdGl2ZSwgeCA9IH5TdWJqZWN0TGV2ZWwsIHdpZHRoPTEwMDApICU+JQogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfU3RyYWlnaHQsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfMV9UdXJuaW5nLCBuYW1lID0gJ05vcm1hbCAtIE1lYW4gUFAgKFR1cm5pbmcpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UodHlwZT0iYmFyIiwgeSA9IH5NZWFuX1BQXzJfQWNjSGlnaCwgd2lkdGg9MS41OCwgbmFtZSA9ICfOlFBQIGFmdGVyIEhBIGluIENEJywgbWFya2VyPUNPTE9SX0NPR05JVElWRV9BQ0MpICU+JSAKICAjIGFkZF90cmFjZSh5ID0gfk1lYW5fUFBfMl9BY2NMb3csIG5hbWUgPSAnQ29naW5pdGl2ZSAtIE1lYW4gUFAgKExvdyBBY2NlbC4pJywgbWFya2VyPUNPTE9SX0FDQykgJT4lIAogIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHR5cGU9ImJhciIsIHkgPSB+TWVhbl9QUF8zX0FjY0hpZ2gsIHdpZHRoPTEuNTgsIG5hbWUgPSAizpRQUCBhZnRlciBIQSBpbiBNRCIsIG1hcmtlcj1DT0xPUl9NT1RPUklDX0FDQykgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+TWVhbl9QUF8zX0FjY0xvdywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoTG93IEFjY2VsLiknLCBtYXJrZXI9Q09MT1JfQUNDKSAlPiUKICAKICAjIGFkZF90cmFjZSh5ID0gflBQX1ByaW9yLCBuYW1lID0gJ0ZhaWx1cmUgLSBQcmlvciBQUCcsIG1hcmtlcj1DT0xPUl9GQUlMVVJFX1BSSU9SKSAlPiUKICBhZGRfdHJhY2UodHlwZT0iYmFyIiwgeSA9IH5QUF9BZnRlciwgd2lkdGg9MS41OCwgbmFtZSA9ICfOlFBQIGFmdGVyIHRoZSBjYXRhc3Ryb3BoaWMgZXZlbnQnLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PS01LCB4ZW5kPWJhcmdhcCAqIG5yb3coY29tYmluZWREZl9Ob1N0cmVzc29yKSwgeSA9IFRIUkVTSE9MRF9NSUxELCB5ZW5kID0gVEhSRVNIT0xEX01JTEQsIG5hbWU9Ik90c3UgVGhyZXNob2xkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgIyBhZGRfc2VnbWVudHMoeD0iIzAxIiwgeGVuZD0iIzQxIiwgeSA9IFRIUkVTSE9MRF9FWFRSRU1FLCB5ZW5kID0gVEhSRVNIT0xEX0VYVFJFTUUsIG5hbWU9IlRocmVzaG9sZDogRXh0cmVtZSBDaGFuZ2Ugb2YgUFAiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iZGFya3JlZCIsIGRhc2ggPSAnZG90JykpICU+JQogIGxheW91dCh5YXhpcyA9IHlBeGlzLCB4YXhpcz14QXhpcywgYmFybW9kZSA9ICdncm91cCcsIGJhcmdhcD01LCB0aXRsZT1GKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Db2duaXRpdmUpCmBgYAoKCgpgYGB7ciwgd2FybmluZz1GfQp4QXhpcyA9IGxpc3QoCiAgdGl0bGUgPSAiU3ViamVjdCIsCiAgdGlja3RleHQgPSBjb21iaW5lZERmX01vdG9yaWMkU3ViamVjdCwgCiAgdGlja3ZhbHMgPSBzZXEoMSwgYmFyZ2FwICogbnJvdyhjb21iaW5lZERmX01vdG9yaWMpLCBieT1iYXJnYXApLAogIHRpY2ttb2RlID0gImFycmF5IgopCmNvbWJpbmVkRGZfTW90b3JpYyRTdWJqZWN0TGV2ZWwgPC0gc2VxKDEsIGJhcmdhcCAqIG5yb3coY29tYmluZWREZl9Nb3RvcmljKSwgYnk9YmFyZ2FwKQoKZmlnX01vdG9yaWMgPC0gcGxvdF9seShjb21iaW5lZERmX01vdG9yaWMsIHggPSB+U3ViamVjdExldmVsLCB3aWR0aD0xMDAwKSAlPiUKICAjIGFkZF90cmFjZSh5ID0gflBQX0Rldl8yX1N0cmFpZ2h0LCBuYW1lID0gJ0NvZ25pdGl2ZSAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JQogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzFfVHVybmluZywgbmFtZSA9ICdOb3JtYWwgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICAjIGFkZF90cmFjZSh5ID0gflBQX0Rldl8yX1R1cm5pbmcsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUgCiAgYWRkX3RyYWNlKHR5cGU9ImJhciIsIHkgPSB+TWVhbl9QUF8yX0FjY0hpZ2gsIHdpZHRoPTEuNTgsIG5hbWUgPSAnzpRQUCBhZnRlciBIQSBpbiBDRCcsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkVfQUNDKSAlPiUgCiAgIyBhZGRfdHJhY2UoeSA9IH5NZWFuX1BQXzJfQWNjTG93LCBuYW1lID0gJ0NvZ2luaXRpdmUgLSBNZWFuIFBQIChMb3cgQWNjZWwuKScsIG1hcmtlcj1DT0xPUl9BQ0MpICU+JSAKICAKICAjIGFkZF90cmFjZSh5ID0gflBQX0Rldl8zX1N0cmFpZ2h0LCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChTdHJhaWdodCknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogICMgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfVHVybmluZywgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoVHVybmluZyknLCBtYXJrZXI9Q09MT1JfTU9UT1JJQykgJT4lIAogIGFkZF90cmFjZSh0eXBlPSJiYXIiLCB5ID0gfk1lYW5fUFBfM19BY2NIaWdoLCB3aWR0aD0xLjU4LCBuYW1lID0gIs6UUFAgYWZ0ZXIgSEEgaW4gTUQiLCBtYXJrZXI9Q09MT1JfTU9UT1JJQ19BQ0MpICU+JSAKICAjIGFkZF90cmFjZSh5ID0gfk1lYW5fUFBfM19BY2NMb3csIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKExvdyBBY2NlbC4pJywgbWFya2VyPUNPTE9SX0FDQykgJT4lCiAgCiAgIyBhZGRfdHJhY2UoeSA9IH5QUF9QcmlvciwgbmFtZSA9ICdGYWlsdXJlIC0gUHJpb3IgUFAnLCBtYXJrZXI9Q09MT1JfRkFJTFVSRV9QUklPUikgJT4lCiAgYWRkX3RyYWNlKHR5cGU9ImJhciIsIHkgPSB+UFBfQWZ0ZXIsIHdpZHRoPTEuNTgsIG5hbWUgPSAnzpRQUCBhZnRlciB0aGUgY2F0YXN0cm9waGljIGV2ZW50JywgbWFya2VyPUNPTE9SX0ZBSUxVUkUpICU+JSAKICBhZGRfc2VnbWVudHMoeD0tNSwgeGVuZD1iYXJnYXAgKiBucm93KGNvbWJpbmVkRGZfTm9TdHJlc3NvciksIHkgPSBUSFJFU0hPTERfTUlMRCwgeWVuZCA9IFRIUkVTSE9MRF9NSUxELCBuYW1lPSJPdHN1IFRocmVzaG9sZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICMgYWRkX3NlZ21lbnRzKHg9IiMwMSIsIHhlbmQ9IiM0MSIsIHkgPSBUSFJFU0hPTERfRVhUUkVNRSwgeWVuZCA9IFRIUkVTSE9MRF9FWFRSRU1FLCBuYW1lPSJUaHJlc2hvbGQ6IEV4dHJlbWUgQ2hhbmdlIG9mIFBQIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgeGF4aXM9eEF4aXMsIGJhcm1vZGUgPSAnZ3JvdXAnLCBiYXJnYXA9NSwgdGl0bGU9RikKCmh0bWx0b29sczo6dGFnTGlzdChmaWdfTW90b3JpYykKYGBgCgoKYGBge3J9CmxpYnJhcnkobmxtZSkKY29tYmluZWREZiRTdWJqZWN0ID0gYXMuZmFjdG9yKGNvbWJpbmVkRGYkU3ViamVjdCkKY29tYmluZWREZiRBY3Rpdml0eSA9IGFzLmZhY3Rvcihjb21iaW5lZERmJEFjdGl2aXR5KQpjb21iaW5lZERmJFBQX0Rldl9Hcm91cCA9IGlmZWxzZShjb21iaW5lZERmJFBQX0RldiA+IFRIUkVTSE9MRF9NSUxELCAxLCAwKQpgYGAKCiMjIyBFeHRyYWN0IGRhdGEgZm9yIGltcG9ydGFudCBmZWF0dXJlcwpgYGB7cn0KaW1wb3J0YW50RmVhdHVyZXNEZiA8LSBjb21iaW5lZERmICU+JSBzZWxlY3QoU3ViamVjdCwgU3RkX1BQXzMsIFBQX0Rldl8yX1R1cm5pbmcsIEFjdGl2aXR5LCBQUF9EZXYsIFBQX0Rldl9Hcm91cCkKYGBgCgojIExpbmVhciBtb2RlbCB3aXRoIGFsbCB2YXJpYWJsZXMKYGBge3J9CmxpbmVhck1vZGVsMSA8LSBsbShQUF9BZnRlciB+IAogICAgICAgICAgICAgICsgUFBfRGV2XzJfU3RyYWlnaHQKICAgICAgICAgICAgICArIFBQX0Rldl8zX1N0cmFpZ2h0CiAgICAgICAgICAgICAgKyBQUF9EZXZfMl9UdXJuaW5nCiAgICAgICAgICAgICAgKyBQUF9EZXZfM19UdXJuaW5nCiAgICAgICAgICAgICAgKyBTdGRfUFBfMl9TdHJhaWdodAogICAgICAgICAgICAgICsgU3RkX1BQXzNfU3RyYWlnaHQKICAgICAgICAgICAgICArIFN0ZF9QUF8yX1R1cm5pbmcKICAgICAgICAgICAgICArIFN0ZF9QUF8zX1R1cm5pbmcKICAgICAgICAgICAgICArIFBQX1ByaW9yCiAgICAgICAgICAgICAgKyBmYWN0b3IoQWN0aXZpdHlFbmNvZGVkKSwgCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWwxKQpwbG90KGxpbmVhck1vZGVsMSkKYGBgCgpgYGB7cn0KbGluZWFyTW9kZWwxIDwtIGxtKFBQX0FmdGVyIH4gCiAgICAgICAgICAgICAgICBNZWFuX1BQXzJfQWNjSGlnaAogICAgICAgICAgICAgICsgTWVhbl9QUF8yX0FjY0xvdwogICAgICAgICAgICAgICsgTWVhbl9QUF8zX0FjY0hpZ2gKICAgICAgICAgICAgICArIE1lYW5fUFBfM19BY2NMb3cKICAgICAgICAgICAgICArIFN0ZF9QUF8yX0FjY0hpZ2gKICAgICAgICAgICAgICArIFN0ZF9QUF8yX0FjY0xvdwogICAgICAgICAgICAgICsgU3RkX1BQXzNfQWNjSGlnaAogICAgICAgICAgICAgICsgU3RkX1BQXzNfQWNjTG93CiAgICAgICAgICAgICAgIyArIFBQX1ByaW9yCiAgICAgICAgICAgICAgKyBmYWN0b3IoQWN0aXZpdHlFbmNvZGVkKSwgCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobGluZWFyTW9kZWwxKQpwbG90KGxpbmVhck1vZGVsMSkKYGBgCgojIyBXaXRoIFByaW9yCmBgYHtyfQpsaW5lYXJNb2RlbFdQcmlvciA8LSBsbShQUF9BZnRlciB+IAogICAgICAgICAgICAgICAgTWVhbl9QUF8yX0FjY0hpZ2gKICAgICAgICAgICAgICArIE1lYW5fUFBfMl9BY2NMb3cKICAgICAgICAgICAgICArIE1lYW5fUFBfM19BY2NIaWdoCiAgICAgICAgICAgICAgKyBNZWFuX1BQXzNfQWNjTG93CiAgICAgICAgICAgICAgKyBTdGRfUFBfMl9BY2NIaWdoCiAgICAgICAgICAgICAgKyBTdGRfUFBfMl9BY2NMb3cKICAgICAgICAgICAgICArIFN0ZF9QUF8zX0FjY0hpZ2gKICAgICAgICAgICAgICArIFN0ZF9QUF8zX0FjY0xvdwogICAgICAgICAgICAgICsgUFBfUHJpb3IKICAgICAgICAgICAgICArIGZhY3RvcihBY3Rpdml0eUVuY29kZWQpLCAKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShsaW5lYXJNb2RlbFdQcmlvcikKcGxvdChsaW5lYXJNb2RlbFdQcmlvcikKYGBgCgpgYGB7cn0KbGluZWFyTW9kZWwzIDwtIGxtKFBQX0FmdGVyIH4gCiAgICAgICAgICAgICAgICBNZWFuX1BQXzJfQWNjSGlnaAogICAgICAgICAgICAgICsgTWVhbl9QUF8yX0FjY0xvdwogICAgICAgICAgICAgICsgTWVhbl9QUF8zX0FjY0hpZ2gKICAgICAgICAgICAgICArIE1lYW5fUFBfM19BY2NMb3cKICAgICAgICAgICAgICAjICsgUFBfUHJpb3IKICAgICAgICAgICAgICArIGZhY3RvcihBY3Rpdml0eUVuY29kZWQpLCAKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShsaW5lYXJNb2RlbDMpCnBsb3QobGluZWFyTW9kZWwzKQpgYGAKCgpgYGB7cn0KIyBFeHBvcnQgdGhlIGFub3ZhIHRhYmxlCmxpYnJhcnkoeHRhYmxlKQpsbUNvZWZmcyA8LSBzdW1tYXJ5KGxpbmVhck1vZGVsMykkY29lZmZpY2llbnRzCmxtQW5vdmEgPC0gYW5vdmEobGluZWFyTW9kZWwzKQoKcHJpbnQoeHRhYmxlKGxtQ29lZmZzLCBkaWdpdHM9YygwLDUsNSw1LDUpKSkKcHJpbnQoeHRhYmxlKGxtQW5vdmEpLCBkaWdpdHM9YygwLDUsNSw1LDUpKQoKYGBgCgoKYGBge3J9CnBwQWZ0ZXIgPC0gY29tYmluZWREZiRQUF9BZnRlcgpwcEFmdGVyQXJyYXkgPC0gbWF0cml4KHBwQWZ0ZXIsIG5yb3cgPSAxLG5jb2wgPSBsZW5ndGgocHBBZnRlcikpCiAgCnRocmVzaG9sZFBQQWZ0ZXIgPC0gb3RzdShwcEFmdGVyQXJyYXksIHJhbmdlPWMobWluKHBwQWZ0ZXIpLCBtYXgocHBBZnRlcikpKSAjIEV4cGVjdGVkIFRocmVzaG9sZCA+IDAuMDQyCnByaW50KHBhc3RlMCgnVGhyZXNob2xkOiAnLCB0aHJlc2hvbGRQUEFmdGVyKSkKCnNlbGVjdGVkRGYgPC0gY29tYmluZWREZiAlPiUgc2VsZWN0KAogICAgICAgICAgICAgICAgICAiU3ViamVjdCIsICJBY3Rpdml0eSIsICJQUF9BZnRlciIsICMgIlBQX1ByaW9yIiwKICAgICAgICAgICAgICAgICAgIk1lYW5fUFBfMl9BY2NIaWdoIiwgIk1lYW5fUFBfM19BY2NIaWdoIiwKICAgICAgICAgICAgICAgICAgIk1lYW5fUFBfMl9BY2NMb3ciLCAiTWVhbl9QUF8zX0FjY0xvdyIsCiAgICAgICAgICAgICAgICAgICMgIlN0ZF9QUF8yX0FjY0hpZ2giLCAiU3RkX1BQXzNfQWNjSGlnaCIsCiAgICAgICAgICAgICAgICAgICMgIlN0ZF9QUF8yX0FjY0xvdyIsICJTdGRfUFBfM19BY2NMb3ciCiAgICAgICAgICAgICAgICAgICkKCnNlbGVjdGVkRGYkU3ViamVjdCA8LSBOVUxMCnNlbGVjdGVkRGYkQWN0aXZpdHlfTk8gPC0gaWZlbHNlKHNlbGVjdGVkRGYkQWN0aXZpdHkgPT0gIk5PIiwgMSwgMCkKc2VsZWN0ZWREZiRBY3Rpdml0eV9DIDwtIGlmZWxzZShzZWxlY3RlZERmJEFjdGl2aXR5ID09ICJDIiwgMSwgMCkKc2VsZWN0ZWREZiRBY3Rpdml0eV9NIDwtIGlmZWxzZShzZWxlY3RlZERmJEFjdGl2aXR5ID09ICJNIiwgMSwgMCkKc2VsZWN0ZWREZiRBY3Rpdml0eSA8LSBOVUxMCgojIHNlbGVjdGVkRGYkUFBfRGV2XzFfVHVybmluZyA8LSBOVUxMCiMgc2VsZWN0ZWREZiRTdGRfUFBfMl9TdHJhaWdodCA8LSBOVUxMCiMgc2VsZWN0ZWREZiRTdGRfUFBfMl9UdXJuaW5nIDwtIE5VTEwKIyBzZWxlY3RlZERmJFN0ZF9QUF8zX1N0cmFpZ2h0IDwtIE5VTEwKIyBzZWxlY3RlZERmJFN0ZF9QUF8zX1R1cm5pbmcgPC0gTlVMTAojIAojICMgQWNjb3JkaW5nIHRvIExpbmVhciBtb2RlbAojIHNlbGVjdGVkRGYkUFBfRGV2XzJfU3RyYWlnaHQgPC0gYWJzKHNlbGVjdGVkRGYkUFBfRGV2XzJfU3RyYWlnaHQpCiMgc2VsZWN0ZWREZiRQUF9EZXZfM19TdHJhaWdodCA8LSBhYnMoc2VsZWN0ZWREZiRQUF9EZXZfM19TdHJhaWdodCkKIyBzZWxlY3RlZERmJFBQX0Rldl8yX1R1cm5pbmcgPC0gYWJzKHNlbGVjdGVkRGYkUFBfRGV2XzJfVHVybmluZykKIyBzZWxlY3RlZERmJFBQX0Rldl8zX1R1cm5pbmcgPC0gYWJzKHNlbGVjdGVkRGYkUFBfRGV2XzNfVHVybmluZykKIyBzZWxlY3RlZERmJFBQX1ByaW9yIDwtIGFicyhzZWxlY3RlZERmJFBQX1ByaW9yKSAjIE5VTEwKCnNlbGVjdGVkRGYkQ2xhc3MgPC0gaWZlbHNlKHNlbGVjdGVkRGYkUFBfQWZ0ZXIgPj0gdGhyZXNob2xkUFBBZnRlciwgVCwgRikKc2VsZWN0ZWREZiRQUF9BZnRlciA8LSBOVUxMCgpwcmludChuYW1lcyhzZWxlY3RlZERmKSkKYGBgCgpgYGB7cn0KIyBsaWJyYXJ5KG1lZmEpCiMgY29tYmluZWREZiA8LSByZXAoY29tYmluZWREZiwgMTApIApgYGAKCmBgYHtyfQpzZXQuc2VlZCgzOSkKbl9mb2xkcyA8LSAzCnBhcmFtcyA8LSBwYXJhbSA8LSBsaXN0KG9iamVjdGl2ZSAgICAgICA9ICJiaW5hcnk6bG9naXN0aWMiLCAKICAgICAgICAgICAgICAgYm9vc3RlciAgICAgICAgICA9ICJnYnRyZWUiLAogICAgICAgICAgICAgICBldmFsX21ldHJpYyAgICAgID0gImF1YyIsCiAgICAgICAgICAgICAgIGV0YSAgICAgICAgICAgICAgPSAwLjEsCiAgICAgICAgICAgICAgIG1heF9kZXB0aCAgICAgICAgPSAxMCwKICAgICAgICAgICAgICAgYWxwaGEgICAgICAgICAgICA9IDEsCiAgICAgICAgICAgICAgIGxhbWJkYSAgICAgICAgICAgPSAwLAogICAgICAgICAgICAgICBnYW1tYSAgICAgICAgICAgID0gMC40NSwKICAgICAgICAgICAgICAgbWluX2NoaWxkX3dlaWdodCA9IDAuMywKICAgICAgICAgICAgICAgc3Vic2FtcGxlICAgICAgICA9IDAuNSwKICAgICAgICAgICAgICAgY29sc2FtcGxlX2J5dHJlZSA9IDEpCiAgICAgICAgICAgCiMgWEdCb29zdCBNb2RlbCAgICAgICAgIAp4Z2JfbSA8LSB4Z2IuY3YoICAgcGFyYW1zICAgICAgICAgICAgICAgPSBwYXJhbSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGFzLm1hdHJpeChzZWxlY3RlZERmICU+JSBzZWxlY3QoLUNsYXNzKSkgLAogICAgICAgICAgICAgICAgICBsYWJlbCA9ICBzZWxlY3RlZERmJENsYXNzLAogICAgICAgICAgICAgICAgICBucm91bmRzICAgICAgICAgICAgID0gMTAwLAogICAgICAgICAgICAgICAgICB2ZXJib3NlICAgICAgICAgICAgID0gRiwKICAgICAgICAgICAgICAgICAgcHJlZGljdGlvbiAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIG1heGltaXplICAgICAgICAgICAgPSBGLCAjIENoYW5nZSB0aGlzIHZhbHVlIHRvIEYgd2lsbCBoZWxwIHRvIHJ1biB3aXRoIG1vcmUgaXRpbmVyYXRpb24KICAgICAgICAgICAgICAgICAgbmZvbGQgICAgICAgICAgICAgICA9IG5fZm9sZHMsCiAgICAgICAgICAgICAgICAgIG1ldHJpY3MgICAgICAgICAgICAgPSBjKCJhdWMiLCAiZXJyb3IiKSwKICAgICAgICAgICAgICAgICAgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gNTAsCiAgICAgICAgICAgICAgICAgIHN0cmF0aWZpZWQgICAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIHNjYWxlX3Bvc193ZWlnaHQgICAgICA9IDEpCgojIHhnYl9tJGV2YWx1YXRpb25fbG9nW3hnYl9tJGJlc3RfaXRlcmF0aW9uLCJ0ZXN0X2F1Y19tZWFuIl0KeGdiX20kZXZhbHVhdGlvbl9sb2dbeGdiX20kYmVzdF9pdGVyYXRpb24sXQoKYGBgCgojIyBQZXJmb3JtYW5jZSBNZXRyaWNzCmBgYHtyfQojIFByZWRpY3Rpb24Kc2VsZWN0ZWREZiRjbHNQcmVkIDwtIHJvdW5kKHhnYl9tJHByZWQpCgpjb21wdXRlUGVyZm9ybWFuY2VSZXN1bHRzIDwtIGZ1bmN0aW9uKHNkYXQpewogIHNkYXQgPSBzZGF0W2NvbXBsZXRlLmNhc2VzKHNkYXQpLF0KICBhY2MgPSBzdW0oc2RhdFssMV0gPT0gc2RhdFssMl0pL25yb3coc2RhdCkKICBjb25mX21hdCA9IHRhYmxlKHNkYXQpCiAgc3BlY2lmID0gY29uZl9tYXRbMSwxXS9zdW0oY29uZl9tYXRbLDFdKQogIHNlbnNpdiA9IGNvbmZfbWF0WzIsMl0vc3VtKGNvbmZfbWF0WywyXSkKICBwcmVjaSA9ICBjb25mX21hdFsyLDJdL3N1bShjb25mX21hdFsyLF0pCiAgbnB2ID0gICAgY29uZl9tYXRbMSwxXS9zdW0oY29uZl9tYXRbMSxdKQogIHJldHVybihjKGFjYyxzcGVjaWYsc2Vuc2l2LHByZWNpLG5wdikpCn0KCiMgR2V0IGF2ZXJhZ2UgcGVyZm9ybWFuY2UKcGVyZm9ybWFuY2UgPC0gY29tcHV0ZVBlcmZvcm1hbmNlUmVzdWx0cyhzZWxlY3RlZERmICU+JSBzZWxlY3QoQ2xhc3MsIGNsc1ByZWQpKQphY2MgPC0gcGVyZm9ybWFuY2VbMV0KcHJlYyA8LSBwZXJmb3JtYW5jZVs0XQpyZWNhbGwgPC0gcGVyZm9ybWFuY2VbM10Kc3BlYyA8LSBwZXJmb3JtYW5jZVsyXQpucHYgPC0gcGVyZm9ybWFuY2VbNV0KZjEgPC0gKDIgKiByZWNhbGwgKiBwcmVjKSAvIChyZWNhbGwgKyBwcmVjKQphdWMgPC0gYXMubnVtZXJpYyh4Z2JfbSRldmFsdWF0aW9uX2xvZ1t4Z2JfbSRiZXN0X2l0ZXJhdGlvbiwgInRlc3RfYXVjX21lYW4iXSkKCnByaW50KHBhc3RlKCJBY2N1cmFjeT0iLCByb3VuZChhY2MsIDIpKSkKcHJpbnQocGFzdGUoIlByZWNpc2lvbj0iLCByb3VuZChwcmVjLCAyKSkpCnByaW50KHBhc3RlKCJSZWNhbGw9Iiwgcm91bmQocmVjYWxsLCAyKSkpCnByaW50KHBhc3RlKCJTcGVjaWZpY2l0eT0iLCByb3VuZChzcGVjLCAyKSkpCnByaW50KHBhc3RlKCJOUFY9Iiwgcm91bmQobnB2LCAyKSkpCnByaW50KHBhc3RlKCJGMT0iLCByb3VuZChmMSwgMikpKQpwcmludChwYXN0ZSgiQVVDPSIsIHJvdW5kKGF1YywgMikpKQpgYGAKCmBgYHtyfQojIEltcG9ydGFuY2UKYnN0IDwtIHhnYm9vc3QoICAgcGFyYW1zICAgICAgICAgICAgICAgPSBwYXJhbSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGFzLm1hdHJpeChzZWxlY3RlZERmICU+JSBzZWxlY3QoLWMoQ2xhc3MsIGNsc1ByZWQpKSkgLAogICAgICAgICAgICAgICAgICBsYWJlbCA9ICBzZWxlY3RlZERmJENsYXNzLAogICAgICAgICAgICAgICAgICBucm91bmRzICAgICAgICAgICAgID0gMTAwLAogICAgICAgICAgICAgICAgICB2ZXJib3NlICAgICAgICAgICAgID0gRiwKICAgICAgICAgICAgICAgICAgcHJlZGljdGlvbiAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIG1heGltaXplICAgICAgICAgICAgPSBGLCAjIENoYW5nZSB0aGlzIHZhbHVlIHRvIEYgd2lsbCBoZWxwIHRvIHJ1biB3aXRoIG1vcmUgaXRpbmVyYXRpb24KICAgICAgICAgICAgICAgICAgbmZvbGQgICAgICAgICAgICAgICA9IG5fZm9sZHMsCiAgICAgICAgICAgICAgICAgIG1ldHJpY3MgICAgICAgICAgICAgPSBjKCJhdWMiLCAiZXJyb3IiKSwKICAgICAgICAgICAgICAgICAgZWFybHlfc3RvcHBpbmdfcm91bmRzID0gNTAsCiAgICAgICAgICAgICAgICAgIHN0cmF0aWZpZWQgICAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIHNjYWxlX3Bvc193ZWlnaHQgICAgICA9IDEpCmltcG9ydGFuY2VEZiA8LSB4Z2IuaW1wb3J0YW5jZShjb2xuYW1lcyhzZWxlY3RlZERmICU+JSBzZWxlY3QoLWMoQ2xhc3MsIGNsc1ByZWQpKSksIG1vZGVsID0gYnN0KQpwcmludChpbXBvcnRhbmNlRGYpCmBgYAoKYGBge3J9CmxpYnJhcnkocFJPQykKCmRmUk9DIDwtIHBST0M6OnJvYyhyZXNwb25zZSA9IGlmZWxzZShzZWxlY3RlZERmJENsYXNzPT1ULCAxLCAwKSwKICAgICAgICAgICAgICAgcHJlZGljdG9yID0gcm91bmQoeGdiX20kcHJlZCksCiAgICAgICAgICAgICAgIGxldmVscz1jKDAsIDEpLCBkaXJlY3Rpb24gPSAiPCIpCgojIGl0ID0gd2hpY2gubWF4KHhnYl9tJGV2YWx1YXRpb25fbG9nJHRlc3RfYXVjX21lYW4pCiMgYmVzdC5pdGVyID0geGdiX20kZXZhbHVhdGlvbl9sb2ckaXRlcltpdF0KIyBiZXN0Lml0ZXIgCgpwbG90KHBST0M6OnJvYyhyZXNwb25zZSA9IGlmZWxzZShzZWxlY3RlZERmJENsYXNzPT1ULCAxLCAwKSwKICAgICAgICAgICAgICAgcHJlZGljdG9yID0gcm91bmQoeGdiX20kcHJlZCksCiAgICAgICAgICAgICAgIGxldmVscz1jKDAsIDEpLCBkaXJlY3Rpb24gPSAiPCIpLCAKICAgICBsZWdhY3kuYXhlcyA9IFRSVUUsCiAgICAgbWFpbj0iUk9DIEN1cnZlIiwgCiAgICAgbHdkPTEuNSkgCmBgYAoKCiMjIyBQbG90IGZlYXR1cmUgaW1wb3J0YW5jZQpgYGB7cn0KeUF4aXMgPC0gbGlzdCgKICB0aXRsZSA9ICdJbXBvcnRhbmNlJywKICByYW5nZT1jKDAuMCwgMS4wKQopCnhBeGlzIDwtIGxpc3QoCiAgdGl0bGUgPSAnRmVhdHVyZScKKQoKaW1wb3J0YW5jZURmJEZlYXR1cmUgPC0gZmFjdG9yKGltcG9ydGFuY2VEZiRGZWF0dXJlLCBsZXZlbHMgPSBpbXBvcnRhbmNlRGZbb3JkZXIoLUdhaW4pLF0kRmVhdHVyZSkKZmlnX0ltcG9ydGFuY2UgPC0gcGxvdF9seShpbXBvcnRhbmNlRGYsIHggPSB+RmVhdHVyZSwgeSA9IH5HYWluLCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnR2FpbicsIHdpZHRoPTYwMCkgJT4lCiAgYWRkX3RyYWNlKHkgPSB+Q292ZXIsIG5hbWUgPSAnQ292ZXInKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+RnJlcXVlbmN5LCBuYW1lID0gJ0ZyZXF1ZW5jeScpICU+JSAKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgeGF4aXM9eEF4aXMsIGJhcm1vZGUgPSAnZ3JvdXAnLCB0aXRsZT0iRmVhdHVyZSBJbXBvcnRhbmNlIikgJT4lIAogIGNvbmZpZyguTGFzdC52YWx1ZSwgbWF0aGpheCA9ICdjZG4nKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19JbXBvcnRhbmNlKQpgYGAKCmBgYHtyfQphY3R1YWxDbHVzdGVyIDwtIGRhdGEuZnJhbWUoY2JpbmQoYXMuY2hhcmFjdGVyKGNvbWJpbmVkRGYkU3ViamVjdCksIHNlbGVjdGVkRGYkQ2xhc3MpKQpuYW1lcyhhY3R1YWxDbHVzdGVyKSA8LSBjKCJTdWJqZWN0IiwgIkNsYXNzIikKYWN0dWFsQ2x1c3RlcgojIGFjdHVhbENsdXN0ZXJbb3JkZXIoQ2xhc3MpLF0KYGBgCgpgYGB7cn0KbGlicmFyeShmYWN0b2V4dHJhKQpsaWJyYXJ5KGNsdXN0ZXIpCmNsdXN0ZXJpbmdEZiA8LSBjb21iaW5lZERmICU+JSBzZWxlY3QoIk1lYW5fUFBfMl9BY2NIaWdoIiwgIk1lYW5fUFBfM19BY2NIaWdoIikgIyhpbXBvcnRhbmNlRGYkRmVhdHVyZVsxOjNdKQpyb3duYW1lcyhzZWxlY3RlZERmKSA8LSBwYXN0ZTAoY29tYmluZWREZiRTdWJqZWN0KQpyb3duYW1lcyhjbHVzdGVyaW5nRGYpIDwtIHBhc3RlMChjb21iaW5lZERmJFN1YmplY3QpCmZpdCA8LSBrbWVhbnMoY2x1c3RlcmluZ0RmLCAzKQojIGNsdXNwbG90KGNsdXN0ZXJpbmdEZiwgZml0JGNsdXN0ZXIsIGNvbG9yPVRSVUUsIHNoYWRlPVRSVUUsIGxhYmVscz0yLCBsaW5lcz0wKQpmdml6X2NsdXN0ZXIoZml0LCBkYXRhPXNlbGVjdGVkRGYpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGRlbmRleHRlbmQpCgpOVU1CRVJfT0ZfQ0xVU1RFUlMgPSA0CkNMVVNURVJfQ09MT1JTIDwtIGMoInJlZCIsICJibHVlIiwgY29sb3JfZGFya3BpbmssIGNvbG9yX2RhcmtwaW5rKQoKY29sb3JfZGFya3BpbmsgPSAiI2U3NTQ4MCIKQ0xVU1RFUl9CUkFOQ0hfQ09MT1JTIDwtIENMVVNURVJfQ09MT1JTWzE6TlVNQkVSX09GX0NMVVNURVJTXQpDTFVTVEVSX0xBQkVMX0NPTE9SUyA8LSBDTFVTVEVSX0NPTE9SU1sxOk5VTUJFUl9PRl9DTFVTVEVSU10KCmJlaGF2aW9yYWxNYXRyaXhDbHVzdGVyaW5nIDwtIGFzLm1hdHJpeChjbHVzdGVyaW5nRGYpCnJvd25hbWVzKGJlaGF2aW9yYWxNYXRyaXhDbHVzdGVyaW5nKSA8LSBwYXN0ZTAoY29tYmluZWREZiRTdWJqZWN0KQpkaXN0TWF0cml4IDwtIGRpc3QoYmVoYXZpb3JhbE1hdHJpeENsdXN0ZXJpbmcsIG1ldGhvZD0ibWFuaGF0dGFuIikKaHJlc3VsdHMgPC0gZGlzdE1hdHJpeCAlPiUgaGNsdXN0KG1ldGhvZD0iY29tcGxldGUiKQoKaGMgPC0gaHJlc3VsdHMgJT4lIAogICAgICBhcy5kZW5kcm9ncmFtICU+JQogICAgICBzZXQoIm5vZGVzX2NleCIsIE5VTUJFUl9PRl9DTFVTVEVSUykgJT4lCiAgICAgIHNldCgibGFiZWxzX2NvbCIsIHZhbHVlID0gQ0xVU1RFUl9MQUJFTF9DT0xPUlMsIGs9TlVNQkVSX09GX0NMVVNURVJTKSAlPiUKICAgICAgIyBzZXQoImxlYXZlc19wY2giLCAxOSkgJT4lCiAgICAgICMgc2V0KCJsZWF2ZXNfY29sIiwgdmFsdWUgPSBjKCJncmF5IiksIGs9TlVNQkVSX09GX0NMVVNURVJTKSAlPiUgICAgCiAgICAgIHNldCgiYnJhbmNoZXNfa19jb2xvciIsIHZhbHVlPUNMVVNURVJfQlJBTkNIX0NPTE9SUywgaz1OVU1CRVJfT0ZfQ0xVU1RFUlMpCgpwbG90KGhjKQpsZWdlbmQoInRvcHJpZ2h0IiwgCiAgICAgdGl0bGU9IkRyaXZlPUZhaWx1cmUgXG5DaGFuZ2Ugb2YgQXJvdXNhbCIsCiAgICAgbGVnZW5kID0gYygiRXhjZXB0aW9uYWwgSW5jcmVhc2UiICwgIk5vdGljYWJsZSBJbmNyZWFzZSIgLCAiTm8tY2hhbmdlIG9yIERlY3JlYXNlIiksIAogICAgIGNvbCA9IGMoInJlZCIsICJwaW5rIiAsICJibHVlIiksCiAgICAgcGNoID0gYygyMCwyMCwyMCksIGJ0eSA9ICJuIiwgIHB0LmNleCA9IDEuNSwgY2V4ID0gMC44ICwgCiAgICAgdGV4dC5jb2wgPSAiYmxhY2siLCBob3JpeiA9IEZBTFNFLCBpbnNldCA9IGMoMC4wLCAwLjEpKQpgYGAKCmBgYHtyfQpOVU1CRVJfT0ZfQ0xVU1RFUlMgPC0gMgpDTFVTVEVSX0NPTE9SUyA8LSBjKCJyZWQiLCAiYmx1ZSIsIGNvbG9yX2RhcmtwaW5rLCBjb2xvcl9kYXJrcGluaykKCmNvbG9yX2RhcmtwaW5rID0gIiNlNzU0ODAiCkNMVVNURVJfQlJBTkNIX0NPTE9SUyA8LSBDTFVTVEVSX0NPTE9SU1sxOk5VTUJFUl9PRl9DTFVTVEVSU10KQ0xVU1RFUl9MQUJFTF9DT0xPUlMgPC0gQ0xVU1RFUl9DT0xPUlNbMTpOVU1CRVJfT0ZfQ0xVU1RFUlNdCgpjb21iaW5lZERmJGlzTSA8LSBpZmVsc2UoY29tYmluZWREZiRBY3Rpdml0eSA9PSAiTSIsIDAuMSwgMCkKY29tYmluZWREZiRpc0MgPC0gaWZlbHNlKGNvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIkMiLCAwLjEsIDApCmNvbWJpbmVkRGYkaXNOIDwtIGlmZWxzZShjb21iaW5lZERmJEFjdGl2aXR5ID09ICJOTyIsIDAuMSwgMCkKCmJlaGF2aW9yYWxNYXRyaXhDbHVzdGVyaW5nIDwtIGFzLm1hdHJpeChjb21iaW5lZERmICU+JSBzZWxlY3QoIlBQX0FmdGVyIiwgImlzTSIsICJpc0MiLCAiaXNOIikpCnJvd25hbWVzKGJlaGF2aW9yYWxNYXRyaXhDbHVzdGVyaW5nKSA8LSBwYXN0ZTAoY29tYmluZWREZiRTdWJqZWN0KQpkaXN0TWF0cml4IDwtIGRpc3QoYmVoYXZpb3JhbE1hdHJpeENsdXN0ZXJpbmcsIG1ldGhvZD0ibWFuaGF0dGFuIikKaHJlc3VsdHMgPC0gZGlzdE1hdHJpeCAlPiUgaGNsdXN0KG1ldGhvZD0iY29tcGxldGUiKQoKaGMgPC0gaHJlc3VsdHMgJT4lIAogICAgICBhcy5kZW5kcm9ncmFtICU+JQogICAgICBzZXQoIm5vZGVzX2NleCIsIE5VTUJFUl9PRl9DTFVTVEVSUykgJT4lCiAgICAgIHNldCgibGFiZWxzX2NvbCIsIHZhbHVlID0gQ0xVU1RFUl9MQUJFTF9DT0xPUlMsIGs9TlVNQkVSX09GX0NMVVNURVJTKSAlPiUKICAgICAgIyBzZXQoImxlYXZlc19wY2giLCAxOSkgJT4lCiAgICAgICMgc2V0KCJsZWF2ZXNfY29sIiwgdmFsdWUgPSBjKCJncmF5IiksIGs9TlVNQkVSX09GX0NMVVNURVJTKSAlPiUgICAgCiAgICAgIHNldCgiYnJhbmNoZXNfa19jb2xvciIsIHZhbHVlPUNMVVNURVJfQlJBTkNIX0NPTE9SUywgaz1OVU1CRVJfT0ZfQ0xVU1RFUlMpCgpwbG90KGhjKQpsZWdlbmQoInRvcHJpZ2h0IiwgCiAgICAgdGl0bGU9IkRyaXZlPUZhaWx1cmUgXG5DaGFuZ2Ugb2YgQXJvdXNhbCIsCiAgICAgbGVnZW5kID0gYygiRXhjZXB0aW9uYWwgSW5jcmVhc2UiICwgIk5vdGljYWJsZSBJbmNyZWFzZSIgLCAiTm8tY2hhbmdlIG9yIERlY3JlYXNlIiksIAogICAgIGNvbCA9IGMoInJlZCIsICJwaW5rIiAsICJibHVlIiksCiAgICAgcGNoID0gYygyMCwyMCwyMCksIGJ0eSA9ICJuIiwgIHB0LmNleCA9IDEuNSwgY2V4ID0gMC44ICwgCiAgICAgdGV4dC5jb2wgPSAiYmxhY2siLCBob3JpeiA9IEZBTFNFLCBpbnNldCA9IGMoMC4wLCAwLjEpKQpgYGA=